package com.peas.platform.common.core.configuration;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.peas.platform.common.core.constant.Constants;
import com.peas.platform.common.core.exception.BaseException;
import com.peas.platform.common.core.interceptor.BaseInterceptor;
import com.peas.platform.common.core.utils.RequestUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author caizhh
 */
@Component
@Slf4j
public class AlphaInterceptor implements HandlerInterceptor {

    @Value("${spring.profiles.active:local}")
    private String profiles;

    @Resource
    private ApplicationContext ac;

    @SneakyThrows
    @Override
    @SuppressWarnings("NullableProblems")
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) {
        String url = request.getRequestURI().toLowerCase();
        String adminLogin = request.getContextPath() + "/api/v1/admin/login";
        String adminCode = request.getContextPath() + "/api/v1/admin/code";
        String adminLogout = request.getContextPath() + "/api/v1/admin/logout";
        String adminPasswordChange = request.getContextPath() + "/api/v1/admin/password/change";
        String adminPasswordReset = request.getContextPath() + "/api/v1/admin/password/reset";
        String swaggerUi = request.getContextPath() + "/swagger-ui/index.html";
        String knifeUi = request.getContextPath() + "/doc.html";
        if (!StrUtil.startWith(url, "/api")) {
            return true;
        }
        if (url.equalsIgnoreCase(adminLogin)
                || url.equalsIgnoreCase(adminCode)
                || url.equalsIgnoreCase(adminLogout)
                || url.equalsIgnoreCase(adminPasswordChange)
                || url.equalsIgnoreCase(adminPasswordReset)) {
            return true;
        }
        if (StrUtil.equals(profiles, "production") && StrUtil.equalsIgnoreCase(url, swaggerUi)) {
            throw new BaseException(Constants.DEFAULT_ERROR_CODE, "Swagger UI禁止访问");
        }
        if (StrUtil.equals(profiles, "production") && StrUtil.equalsIgnoreCase(url, knifeUi)) {
            throw new BaseException(Constants.DEFAULT_ERROR_CODE, "禁止访问");
        }
        // requestId
        RequestUtil.initRequestId(request);
        //request.setAttribute();
        log.debug(request.getRequestURI() + " Start");
        log.debug("request.getContextPath():" + request.getContextPath());
        List<BaseInterceptor> list = getBaseInterceptors();
        CollUtil.forEach(list, (CollUtil.Consumer<BaseInterceptor>) (value, index) -> value.preHandle(request, response));
        return true;
    }

    @Override
    @SuppressWarnings("NullableProblems")
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) {
        List<BaseInterceptor> list = getBaseInterceptors();
        CollUtil.forEach(list, (CollUtil.Consumer<BaseInterceptor>) (value, index) -> value.postHandle(request, response));
    }

    @SneakyThrows
    @Override
    @SuppressWarnings("NullableProblems")
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                @Nullable Exception ex) {
        List<BaseInterceptor> list = getBaseInterceptors();
        CollUtil.forEach(list, (CollUtil.Consumer<BaseInterceptor>) (value, index) -> value.afterCompletion(request, response));
        Map<RequestContextUtilEnum, String> context = RequestContextUtil.getCurrentContext();
        RequestContextUtil.close(context);
        log.debug(request.getRequestURI() + " End");
    }

    private List<BaseInterceptor> getBaseInterceptors() {
        List<BaseInterceptor> list = Collections.emptyList();
        Map<String, BaseInterceptor> beans = ac.getBeansOfType(BaseInterceptor.class);
        if (CollUtil.isNotEmpty(beans)) {
            list = new ArrayList<>(beans.values());
            list.sort((o1, o2) -> o1.sort() == null ? 1 : o2.sort() == null ? -1 : o1.sort().compareTo(o2.sort()));
        }
        return list;
    }

}
